// Copyright 2017 Baidu Inc. All Rights Reserved.
// Author: tai xiurong (taixiurong@baidu.com)
//
// Description:

#include "baidu_speex_encoder.h"
#include "baidu_speex.h"
#include "baidu_time_calculate.h"
#include "heap_monitor.h"
#include "duer_log.h"
namespace duer {

SpeexEncoder::SpeexEncoder(size_t buff_size, void* buff) :
        _buff(buff),
        _capacity(buff_size),
        _data(NULL),
        _size(0),
        _valid_record(false) {
    if (_buff == NULL && _capacity > 0) {
        _data = NEW(RECORDER) char[_capacity];
    }
}
SpeexEncoder::SpeexEncoder() :
        _buff(NULL),
        _capacity(s_i_buffer_len),
        _data(NULL),
        _size(0),
        _valid_record(false) {
    if (_buff == NULL && _capacity > 0) {
        _data = NEW(RECORDER) char[_capacity];
    }
}

SpeexEncoder::~SpeexEncoder() {
    if (_buff == NULL && _capacity > 0) {
        delete _data;
    }
}

#if 0
static int count =1;
FILE * fp;
#endif

int SpeexEncoder::on_start() {
    bdspx_speex_init(SPEEX_SAMPLE_RATE, &_encoder_buffer);
    if (_valid_record) {
        _valid_record = false;
    }

#if 0
	char file[10];
	sprintf(file, "/sd/%d.pcm",count++);
	fp = fopen(file,"wb"); 
#endif
    return process_start();
}

int SpeexEncoder::on_resume() {
    return process_resume();
}

int SpeexEncoder::on_data(const void* data, size_t size) {
    int io_len = size;
    int ret = 0;
    DUER_LOGV("SpeexEncoder::on_data: size = %d", size);
	

#if 0
	fwrite(data,1,size,fp);
#endif

    ret = bdspx_speex_encode((char*)data, &io_len, 0, recorder_output_handler, this, _encoder_buffer);
    return ret;
}

int SpeexEncoder::on_pause() {
    return process_pause();
}

int SpeexEncoder::on_stop() {
    if (_valid_record) {
        if (_size  > 0) {
            process_data(_data, _size);
        }
        _valid_record = false;
    } else if (_size > _min_valid_size) {
        process_data(_data, _size);
    } else if (_size > 0) {
        DUER_LOGI("SpeexEncoder, drop invalid record data size: %d, min_valid_size:%d\n", _size,
                _min_valid_size);
        Recorder::add_drop_invalid_record();
    }
    _size = 0;
    int rs = process_stop();
    bdspx_speex_destroy(_encoder_buffer);

#if 0
	fclose(fp);
#endif


    return rs;
}

void SpeexEncoder::recorder_output_handler(void* ctx, char* data, int size, int flush) {
    if (ctx == NULL) {
        DUER_LOGI("ctx is null");
        return;
    }
    SpeexEncoder* p_listener = reinterpret_cast<SpeexEncoder*>(ctx);
    PERFORM_STATISTIC_BEGIN(PERFORM_STATISTIC_OUTPUT_RECORDER_DATA, MAX_TIME_CALCULATE_COUNT);
    DUER_LOGV("SpeexEncoder::recorder_output_handler: size = %d", size);
    if (p_listener->_size + size/* + sizeof(size)*/ > p_listener->_capacity) {
        if (!p_listener->_valid_record) {
            p_listener->_valid_record = true;
        }
        p_listener->process_data(p_listener->_data, p_listener->_size);
        p_listener->_size = 0;
    }
    memmove(p_listener->_data + p_listener->_size, data, size);
    p_listener->_size += size;
    PERFORM_STATISTIC_END(PERFORM_STATISTIC_OUTPUT_RECORDER_DATA, size, UNCONTINUOUS_TIME_MEASURE);
}
}//duer

